home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oh!X 2000 Spring
/
Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).7z
/
Oh!X 2000 Spring Special CD-ROM (Japan) (Part 1).bin
/
MIPSSIM
/
asm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-12-02
|
41KB
|
1,440 lines
#include <stdio.h>
#include "define.h"
void asmips(char *base, FILE *fp);
#define MAXNAME 31
#define MAXLABEL 10000
static ulong PC;
static int linenum;
static struct {
char name[MAXNAME+1];
ulong addr;
} label_table[MAXLABEL];
static int labelp = -1;
#define BC 0
#define JMP 1
#define LA 2
static struct {
char name[MAXNAME+1];
ulong idx;
int typ;
} unsolved[MAXLABEL];
static int unsolvedp = -1;
#define MAXLOCALF 16
static ulong local_label[256];
static int for_llabel[256][MAXLOCALF];
static int typ_llabel[256][MAXLOCALF];
static int for_index[256];
static int search_label(char *);
static int regist_label(char *, ulong);
static void regist_unsolv(char *, ulong, int);
typedef struct {
char *nm;
void (*type)(int);
ulong code;
} TABLE;
static void R_TYPE(int),I_TYPE(int),J_TYPE(int),C_TYPE(int),L_TYPE(int);
static void Z_TYPE(int),X_TYPE(int),S_TYPE(int);
#define _CODE(OP,FN) (ulong)((OP<<26)|FN)
static TABLE nmtab[]={
/* MIPS-I */
"add", R_TYPE, _CODE(000,040),
"addi", I_TYPE, _CODE(010,0),
"addiu", I_TYPE, _CODE(011,0),
"addu", R_TYPE, _CODE(000,041),
"and", R_TYPE, _CODE(000,044),
"andi", I_TYPE, _CODE(014,0),
"bc0f", I_TYPE, _CODE(020,0)|(010<<21)|(000<<16),
"bc1f", I_TYPE, _CODE(021,0)|(010<<21)|(000<<16),
"bc2f", I_TYPE, _CODE(022,0)|(010<<21)|(000<<16),
"bc3f", I_TYPE, _CODE(023,0)|(010<<21)|(000<<16),
"bc0t", I_TYPE, _CODE(020,0)|(010<<21)|(001<<16),
"bc1t", I_TYPE, _CODE(021,0)|(010<<21)|(001<<16),
"bc2t", I_TYPE, _CODE(022,0)|(010<<21)|(001<<16),
"bc3t", I_TYPE, _CODE(023,0)|(010<<21)|(001<<16),
"beq", I_TYPE, _CODE(004,0),
"bgez", I_TYPE, _CODE(001,0)|(001<<16),
"bgezal", I_TYPE, _CODE(001,0)|(021<<16),
"bgtz", I_TYPE, _CODE(007,0),
"blez", I_TYPE, _CODE(006,0),
"bltz", I_TYPE, _CODE(001,0)|(000<<16),
"bltzal", I_TYPE, _CODE(001,0)|(020<<16),
"bne", I_TYPE, _CODE(005,0),
"break", R_TYPE, _CODE(000,015),
"cfc0", R_TYPE, _CODE(020,067)|(002<<21),
"cfc1", R_TYPE, _CODE(021,067)|(002<<21),
"cfc2", R_TYPE, _CODE(022,067)|(002<<21),
"cfc3", R_TYPE, _CODE(023,067)|(002<<21),
"ctc0", R_TYPE, _CODE(020,067)|(006<<21),
"ctc1", R_TYPE, _CODE(021,067)|(006<<21),
"ctc2", R_TYPE, _CODE(022,067)|(006<<21),
"ctc3", R_TYPE, _CODE(023,067)|(006<<21),
"div", R_TYPE, _CODE(000,032),
"divu", R_TYPE, _CODE(000,033),
"j", J_TYPE, _CODE(002,0),
"jal", J_TYPE, _CODE(003,0),
"jalr", R_TYPE, _CODE(000,011),
"jr", R_TYPE, _CODE(000,010),
"lb", L_TYPE, _CODE(040,0),
"lbu", L_TYPE, _CODE(044,0),
"lh", L_TYPE, _CODE(041,0),
"lhu", L_TYPE, _CODE(045,0),
"lui", L_TYPE, _CODE(017,0),
"lw", L_TYPE, _CODE(043,0),
"lwc0", L_TYPE, _CODE(060,0),
"lwc1", L_TYPE, _CODE(061,0),
"lwc2", L_TYPE, _CODE(062,0),
"lwc3", L_TYPE, _CODE(063,0),
"lwl", L_TYPE, _CODE(042,0),
"lwr", L_TYPE, _CODE(046,0),
"mfc0", R_TYPE, _CODE(020,067)|(000<<21),
"mfc1", R_TYPE, _CODE(021,067)|(000<<21),
"mfc2", R_TYPE, _CODE(022,067)|(000<<21),
"mfc3", R_TYPE, _CODE(023,067)|(000<<21),
"mfhi", R_TYPE, _CODE(000,020),
"mflo", R_TYPE, _CODE(000,022),
"mtc0", R_TYPE, _CODE(020,067)|(004<<21),
"mtc1", R_TYPE, _CODE(021,067)|(004<<21),
"mtc2", R_TYPE, _CODE(022,067)|(004<<21),
"mtc3", R_TYPE, _CODE(023,067)|(004<<21),
"mthi", R_TYPE, _CODE(000,021),
"mtlo", R_TYPE, _CODE(000,023),
"mult", R_TYPE, _CODE(000,030),
"multu", R_TYPE, _CODE(000,031),
"nor", R_TYPE, _CODE(000,047),
"or", R_TYPE, _CODE(000,045),
"ori", I_TYPE, _CODE(015,0),
"rfe", C_TYPE, _CODE(020,020)|(1<<25),
"sb", L_TYPE, _CODE(050,0),
"sh", L_TYPE, _CODE(051,0),
"sll", R_TYPE, _CODE(000,000),
"sllv", R_TYPE, _CODE(000,004),
"slt", R_TYPE, _CODE(000,052),
"slti", I_TYPE, _CODE(012,0),
"sltiu", I_TYPE, _CODE(013,0),
"sltu", R_TYPE, _CODE(000,053),
"sra", R_TYPE, _CODE(000,003),
"srav", R_TYPE, _CODE(000,007),
"srl", R_TYPE, _CODE(000,002),
"srlv", R_TYPE, _CODE(000,006),
"sub", R_TYPE, _CODE(000,042),
"subu", R_TYPE, _CODE(000,043),
"sw", L_TYPE, _CODE(053,0),
"swc0", L_TYPE, _CODE(070,0),
"swc1", L_TYPE, _CODE(071,0),
"swc2", L_TYPE, _CODE(072,0),
"swc3", L_TYPE, _CODE(073,0),
"swl", L_TYPE, _CODE(052,0),
"swr", L_TYPE, _CODE(056,0),
"syscall", R_TYPE, _CODE(000,014),
"tlbp", C_TYPE, _CODE(020,010)|(1<<25),
"tlbr", C_TYPE, _CODE(020,001)|(1<<25),
"tlbwi", C_TYPE, _CODE(020,002)|(1<<25),
"tlbwr", C_TYPE, _CODE(020,006)|(1<<25),
"xor", R_TYPE, _CODE(000,046),
"xori", I_TYPE, _CODE(016,0),
/* MIPS-II */
"bc0fl", I_TYPE, _CODE(020,0)|(010<<21)|(002<<16),
"bc1fl", I_TYPE, _CODE(021,0)|(010<<21)|(002<<16),
"bc2fl", I_TYPE, _CODE(022,0)|(010<<21)|(002<<16),
"bc0tl", I_TYPE, _CODE(020,0)|(010<<21)|(003<<16),
"bc1tl", I_TYPE, _CODE(021,0)|(010<<21)|(003<<16),
"bc2tl", I_TYPE, _CODE(022,0)|(010<<21)|(003<<16),
"beql", I_TYPE, _CODE(024,0),
"bgezl", I_TYPE, _CODE(001,0)|(003<<16),
"bgezall", I_TYPE, _CODE(001,0)|(023<<16),
"bgtzl", I_TYPE, _CODE(027,0),
"blezl", I_TYPE, _CODE(026,0),
"bltzl", I_TYPE, _CODE(001,0)|(002<<16),
"bltzall", I_TYPE, _CODE(001,0)|(022<<16),
"bnel", I_TYPE, _CODE(025,0),
"tge", R_TYPE, _CODE(000,060),
"tgeu", R_TYPE, _CODE(000,061),
"tlt", R_TYPE, _CODE(000,062),
"tltu", R_TYPE, _CODE(000,063),
"teq", R_TYPE, _CODE(000,064),
"tne", R_TYPE, _CODE(000,066),
"tgei", I_TYPE, _CODE(001,0)|(010<<16),
"tgeiu", I_TYPE, _CODE(001,0)|(011<<16),
"tlti", I_TYPE, _CODE(001,0)|(012<<16),
"tltiu", I_TYPE, _CODE(001,0)|(013<<16),
"teqi", I_TYPE, _CODE(001,0)|(014<<16),
"tnei", I_TYPE, _CODE(001,0)|(016<<16),
"ll", L_TYPE, _CODE(060,0),
"sc", L_TYPE, _CODE(070,0),
"sync", C_TYPE, _CODE(000,017),
"eret", C_TYPE, _CODE(020,030)|(1<<25),
/* MIPS-III */
"daddi", I_TYPE, _CODE(030,0),
"daddiu", I_TYPE, _CODE(031,0),
"ldl", L_TYPE, _CODE(032,0),
"ldr", L_TYPE, _CODE(033,0),
"sdl", L_TYPE, _CODE(054,0),
"sdr", L_TYPE, _CODE(055,0),
"lld", L_TYPE, _CODE(064,0),
"ldc1", L_TYPE, _CODE(065,0),
"ldc2", L_TYPE, _CODE(066,0),
"ld", L_TYPE, _CODE(067,0),
"lwu", L_TYPE, _CODE(047,0),
"scd", L_TYPE, _CODE(074,0),
"sdc1", L_TYPE, _CODE(075,0),
"sdc2", L_TYPE, _CODE(076,0),
"sd", L_TYPE, _CODE(077,0),
"dmfc0", R_TYPE, _CODE(020,067)|(001<<21),
"dmfc1", R_TYPE, _CODE(021,067)|(001<<21),
"dmfc2", R_TYPE, _CODE(022,067)|(001<<21),
"dmtc0", R_TYPE, _CODE(020,067)|(005<<21),
"dmtc1", R_TYPE, _CODE(021,067)|(005<<21),
"dmtc2", R_TYPE, _CODE(022,067)|(005<<21),
"dsll", R_TYPE, _CODE(000,070),
"dsllv", R_TYPE, _CODE(000,024),
"dsra", R_TYPE, _CODE(000,073),
"dsrav", R_TYPE, _CODE(000,027),
"dsrl", R_TYPE, _CODE(000,072),
"dsrlv", R_TYPE, _CODE(000,026),
"dsll32", R_TYPE, _CODE(000,074),
"dsrl32", R_TYPE, _CODE(000,076),
"dsra32", R_TYPE, _CODE(000,077),
"dmult", R_TYPE, _CODE(000,034),
"dmultu", R_TYPE, _CODE(000,035),
"ddiv", R_TYPE, _CODE(000,036),
"ddivu", R_TYPE, _CODE(000,037),
"dadd", R_TYPE, _CODE(000,054),
"daddu", R_TYPE, _CODE(000,055),
"dsub", R_TYPE, _CODE(000,056),
"dsubu", R_TYPE, _CODE(000,057),
/* MIPS-IV */
"movf", R_TYPE, _CODE(000,001)|(000<<16),
"movt", R_TYPE, _CODE(000,001)|(001<<16),
"movz", R_TYPE, _CODE(000,012),
"movn", R_TYPE, _CODE(000,013),
"pref", Z_TYPE, _CODE(063,0),
"lwxc1", X_TYPE, _CODE(023,000),
"ldxc1", X_TYPE, _CODE(023,001),
"swxc1", X_TYPE, _CODE(023,010),
"sdxc1", X_TYPE, _CODE(023,011),
"prefx", X_TYPE, _CODE(023,017),
"madd.s", X_TYPE, _CODE(023,040),
"madd.d", X_TYPE, _CODE(023,041),
"msub.s", X_TYPE, _CODE(023,050),
"msub.d", X_TYPE, _CODE(023,051),
"nmadd.s", X_TYPE, _CODE(023,060),
"nmadd.d", X_TYPE, _CODE(023,061),
"nmsub.s", X_TYPE, _CODE(023,070),
"nmsub.d", X_TYPE, _CODE(023,071),
/* ETC. */
"cache", Z_TYPE, _CODE(057,0),
"jalx", J_TYPE, _CODE(035,0),
/* MIPS32 */
"madd", S_TYPE, _CODE(034,000),
"maddu", S_TYPE, _CODE(034,001),
"mul", S_TYPE, _CODE(034,002),
"msub", S_TYPE, _CODE(034,004),
"msubu", S_TYPE, _CODE(034,005),
"clz", S_TYPE, _CODE(034,040),
"clo", S_TYPE, _CODE(034,041),
"dclz", S_TYPE, _CODE(034,044),
"dclo", S_TYPE, _CODE(034,045),
"ssnop", C_TYPE, _CODE(034,077),
/*END*/
};
#define MAXTAB (sizeof(nmtab)/sizeof(TABLE))
static char *fnam[]={
"add", "sub", "mul", "div", "sqrt", "abs", "mov", "neg",
"round.l","trunc.l","ceil.l","floor.l","round.w","trunc.w","ceil.w","floor.w",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
"cvt.s","cvt.d","", "", "cvt.w","cvt.l","", "",
"", "", "", "", "", "", "", "",
"c.f", "c.un", "c.eq", "c.ueq","c.olt","c.ult","c.ole","c.ule",
"c.sf", "c.ngle","c.seq","c.ngl","c.lt","c.nge","c.le", "c.ngt"
};
#define MAXBUFF 1024
static char Line[MAXBUFF];
static char tmpBuf[MAXBUFF];
static char *linep;
long gen_val(char*);
static long scan_val(char*, int);
static int regnum( char *reg)
{
int r;
r= 0;
if(strcmp(reg,"r0")==0) r=0;
if(strcmp(reg,"r1")==0) r=1;
if(strcmp(reg,"r2")==0) r=2;
if(strcmp(reg,"r3")==0) r=3;
if(strcmp(reg,"r4")==0) r=4;
if(strcmp(reg,"r5")==0) r=5;
if(strcmp(reg,"r6")==0) r=6;
if(strcmp(reg,"r7")==0) r=7;
if(strcmp(reg,"r8")==0) r=8;
if(strcmp(reg,"r9")==0) r=9;
if(strcmp(reg,"r10")==0) r=10;
if(strcmp(reg,"r11")==0) r=11;
if(strcmp(reg,"r12")==0) r=12;
if(strcmp(reg,"r13")==0) r=13;
if(strcmp(reg,"r14")==0) r=14;
if(strcmp(reg,"r15")==0) r=15;
if(strcmp(reg,"r16")==0) r=16;
if(strcmp(reg,"r17")==0) r=17;
if(strcmp(reg,"r18")==0) r=18;
if(strcmp(reg,"r19")==0) r=19;
if(strcmp(reg,"r20")==0) r=20;
if(strcmp(reg,"r21")==0) r=21;
if(strcmp(reg,"r22")==0) r=22;
if(strcmp(reg,"r23")==0) r=23;
if(strcmp(reg,"r24")==0) r=24;
if(strcmp(reg,"r25")==0) r=25;
if(strcmp(reg,"r26")==0) r=26;
if(strcmp(reg,"r27")==0) r=27;
if(strcmp(reg,"r28")==0) r=28;
if(strcmp(reg,"r29")==0) r=29;
if(strcmp(reg,"r30")==0) r=30;
if(strcmp(reg,"r31")==0) r=31;
if(strcmp(reg,"zero")==0)r=0;
if(strcmp(reg,"at")==0) r=1;
if(strcmp(reg,"v0")==0) r=2;
if(strcmp(reg,"v1")==0) r=3;
if(strcmp(reg,"a0")==0) r=4;
if(strcmp(reg,"a1")==0) r=5;
if(strcmp(reg,"a2")==0) r=6;
if(strcmp(reg,"a3")==0) r=7;
if(strcmp(reg,"t0")==0) r=8;
if(strcmp(reg,"t1")==0) r=9;
if(strcmp(reg,"t2")==0) r=10;
if(strcmp(reg,"t3")==0) r=11;
if(strcmp(reg,"t4")==0) r=12;
if(strcmp(reg,"t5")==0) r=13;
if(strcmp(reg,"t6")==0) r=14;
if(strcmp(reg,"t7")==0) r=15;
if(strcmp(reg,"s0")==0) r=16;
if(strcmp(reg,"s1")==0) r=17;
if(strcmp(reg,"s2")==0) r=18;
if(strcmp(reg,"s3")==0) r=19;
if(strcmp(reg,"s4")==0) r=20;
if(strcmp(reg,"s5")==0) r=21;
if(strcmp(reg,"s6")==0) r=22;
if(strcmp(reg,"s7")==0) r=23;
if(strcmp(reg,"t8")==0) r=24;
if(strcmp(reg,"t9")==0) r=25;
if(strcmp(reg,"k0")==0) r=26;
if(strcmp(reg,"k1")==0) r=27;
if(strcmp(reg,"gp")==0) r=28;
if(strcmp(reg,"sp")==0) r=29;
if(strcmp(reg,"s8")==0) r=30;
if(strcmp(reg,"fp")==0) r=30;
if(strcmp(reg,"ra")==0) r=31;
if(strcmp(reg,"lo")==0) r=32;
if(strcmp(reg,"hi")==0) r=33;
if(strcmp(reg,"C0_Index" )==0) r=0;
if(strcmp(reg,"C0_Random" )==0) r=1;
if(strcmp(reg,"C0_EntryLo" )==0) r=2;
if(strcmp(reg,"C0_EntryLo0")==0) r=2;
if(strcmp(reg,"C0_EntryLo1")==0) r=3;
if(strcmp(reg,"C0_Context" )==0) r=4;
if(strcmp(reg,"C0_PageMask")==0) r=5;
if(strcmp(reg,"C0_Wired" )==0) r=6;
if(strcmp(reg,"C0_Error" )==0) r=7;
if(strcmp(reg,"C0_BadVAddr")==0) r=8;
if(strcmp(reg,"C0_Count" )==0) r=9;
if(strcmp(reg,"C0_ASID" )==0) r=10;
if(strcmp(reg,"C0_EntryHi" )==0) r=10;
if(strcmp(reg,"C0_Compare" )==0) r=11;
if(strcmp(reg,"C0_SR" )==0) r=12;
if(strcmp(reg,"C0_Cause" )==0) r=13;
if(strcmp(reg,"C0_EPC" )==0) r=14;
if(strcmp(reg,"C0_PRId" )==0) r=15;
if(strcmp(reg,"C0_Config" )==0) r=16;
if(strcmp(reg,"C0_LLAddr" )==0) r=17;
if(strcmp(reg,"C0_WatchLo" )==0) r=18;
if(strcmp(reg,"C0_WatchHi" )==0) r=19;
if(strcmp(reg,"C0_XContext")==0) r=20;
if(strcmp(reg,"C0_ECC" )==0) r=26;
if(strcmp(reg,"C0_PErr" )==0) r=26;
if(strcmp(reg,"C0_CacheErr")==0) r=27;
if(strcmp(reg,"C0_TagLo" )==0) r=28;
if(strcmp(reg,"C0_TagHi" )==0) r=29;
if(strcmp(reg,"C0_ErrorEPC")==0) r=30;
if(strcmp(reg,"C1_SR" )==0) r=31;
if(strcmp(reg,"fp0")==0) r=0x00;
if(strcmp(reg,"fp1")==0) r=0x01;
if(strcmp(reg,"fp2")==0) r=0x02;
if(strcmp(reg,"fp3")==0) r=0x03;
if(strcmp(reg,"fp4")==0) r=0x04;
if(strcmp(reg,"fp5")==0) r=0x05;
if(strcmp(reg,"fp6")==0) r=0x06;
if(strcmp(reg,"fp7")==0) r=0x07;
if(strcmp(reg,"fp8")==0) r=0x08;
if(strcmp(reg,"fp9")==0) r=0x09;
if(strcmp(reg,"fp10")==0) r=0x0a;
if(strcmp(reg,"fp11")==0) r=0x0b;
if(strcmp(reg,"fp12")==0) r=0x0c;
if(strcmp(reg,"fp13")==0) r=0x0d;
if(strcmp(reg,"fp14")==0) r=0x0e;
if(strcmp(reg,"fp15")==0) r=0x0f;
if(strcmp(reg,"fp16")==0) r=0x10;
if(strcmp(reg,"fp17")==0) r=0x11;
if(strcmp(reg,"fp18")==0) r=0x12;
if(strcmp(reg,"fp19")==0) r=0x13;
if(strcmp(reg,"fp20")==0) r=0x14;
if(strcmp(reg,"fp21")==0) r=0x15;
if(strcmp(reg,"fp22")==0) r=0x16;
if(strcmp(reg,"fp23")==0) r=0x17;
if(strcmp(reg,"fp24")==0) r=0x18;
if(strcmp(reg,"fp25")==0) r=0x19;
if(strcmp(reg,"fp26")==0) r=0x1a;
if(strcmp(reg,"fp27")==0) r=0x1b;
if(strcmp(reg,"fp28")==0) r=0x1c;
if(strcmp(reg,"fp29")==0) r=0x1d;
if(strcmp(reg,"fp30")==0) r=0x1e;
if(strcmp(reg,"fp31")==0) r=0x1f;
if(strcmp(reg,"pc")==0) r=0x1000;
return r;
}
static int search_label(char *nam)
{
int i;
for(i=0;i<=labelp;i++)
if(strcmp(label_table[i].name,nam)==0)
break;
if(i>labelp) return -1;/* not found */
return i;/* found */
}
static int regist_label(char *nam, ulong pc)
{
if(search_label(nam)>=0)
return -1;/* duplicated definition */
if((labelp+1)>=MAXLABEL)
return -2;/* table overflow */
++labelp;
strncpy(label_table[labelp].name,nam,MAXNAME);
label_table[labelp].addr = pc;
return 0;
}
static void regist_unsolv(char *nam, ulong pc, int typ)
{
if((unsolvedp+1)>=MAXLABEL){
fprintf(stderr,"%d: too many unsolved labels!\n",linenum);
return;
}
unsolvedp++;
strncpy(unsolved[unsolvedp].name,nam,MAXNAME);
unsolved[unsolvedp].idx = pc;
unsolved[unsolvedp].typ = typ;
}
static void add_label(ulong dst, ulong idx, int typ)
{
ulong org;
ulong code;
switch(typ){
case BC:
org = idx;
code = get_word(idx);
code |= ((((dst&0xffff)-(org&0xffff)-4)>>2)&0xffff);
put_word(idx,code);
break;
case JMP:
code = get_word(idx);
code |= ((dst>>2)&0x3ffffff);
put_word(idx,code);
break;
case LA:
code = get_word(idx);
code |= ((dst>>16)&0xffff);
put_word(idx,code);
code = get_word(idx+4);
code |= ((dst )&0xffff);
put_word(idx+4,code);
break;
}
}
static void solve_label(void)
{
int i;
int l;
for(i=0;i<=unsolvedp;i++){
if((l=search_label(unsolved[i].name))<0){
fprintf(stderr,"unsolved label: %s\n",unsolved[i].name);
}
else{
add_label(label_table[l].addr,unsolved[i].idx,unsolved[i].typ);
}
}
}
static void solve_local(int n)
{
int i;
for(i=0;i<=for_index[n];i++){
add_label(local_label[n],for_llabel[n][i],typ_llabel[n][i]);
}
for_index[n] = -1;
}
static int white(int ch)
{
return (ch==' ')||(ch=='\t');
}
static int eol(int ch)
{
return (ch=='\n')||(ch=='\0')||(ch=='\r');
}
static int delim(int ch)
{
return (ch==',')||white(ch)||(ch=='(')||(ch==')')||(ch==':');
}
static void scan_sym(char *to)
{
while(delim(*linep)) linep++;
while((!eol(*linep)) && (!delim(*linep))) *to++ = *linep++;
if(*linep==':'){
*to++ = ':';
linep++;
}
*to='\0';
}
static int chk_num(int ch, int rad)
{
ch &= 0xff;
if(rad<=10){
ch=ch-'0';
if((ch>=0)&&(ch<rad)) return ch;
else return -1;
}
if(rad==16){
if((ch>='0')&&(ch<='9')) return ch-'0';
if((ch>='a')&&(ch<='f')) return ch-'a'+10;
if((ch>='A')&&(ch<='F')) return ch-'A'+10;
return -1;
}
return -1;
}
static char last_ch;
static ulong label_value;
static long scan_val(char *from, int radix)
{
long num=0;
int n;
while(white(*from)) from++;
switch(radix){
case 2:
case 8:
case 10:
case 16:
while(*from){
if((n=chk_num(*from,radix))>=0)
num=num*radix+n;
else
break;
from++;
}
break;
default:
num=gen_val(from);
}
last_ch = *from;
return num;
}
long gen_val(char *from)
{
char ch;
while(white(*from)) from++;
ch = *from++;
if(ch=='0'){
switch(*from){
case 'b': /* binary */
case 'B':
return scan_val(from+1,2);
case 'x': /* hexadecimal */
case 'X':
return scan_val(from+1,16);
default: /* octal */
return scan_val(from,8);
}
}
else if((ch>='0')&&(ch<='9')){
return scan_val(from-1,10);
}
else if(ch=='-'){
return (-1)*gen_val(from);
}
else{
return 0;
}
}
#define LABEL 0
#define LOCALF 1
#define LOCALB 2
#define ADDR 3
static int check_label(char *sym)
{
if((*sym<'0')||(*sym>'9'))
return LABEL;
label_value = (ulong)gen_val(sym);
if(last_ch=='f')
return LOCALF;
if(last_ch=='b')
return LOCALB;
return ADDR;
}
static int islocal(char *sym)
{
int v=0;
while(*sym){
if((*sym<'0')||(*sym>'9'))
break;
v = v*10+(*sym-'0');
sym++;
}
if(*sym=='\0')
return v;
return 0;
}
static void S_TYPE(int insn)
{
int fn;
int rs,rt,rd;
switch((fn=nmtab[insn].code)&0x3f){
case 000:
case 001:
case 004:
case 005:
scan_sym(tmpBuf);
rs=regnum(tmpBuf);
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
rd = 0;
break;
case 040:
case 041:
case 044:
case 045:
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
scan_sym(tmpBuf);
rs=regnum(tmpBuf);
rd = rt;
break;
case 002:
scan_sym(tmpBuf);
rd=regnum(tmpBuf);
scan_sym(tmpBuf);
rs=regnum(tmpBuf);
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
break;
}
fn |= ((rs&0x1f)<<21)|((rt&0x1f)<<16)|((rd&0x1f)<<11);
put_word(PC,fn);
}
static void R_TYPE(int insn)
{
int fn;
int rs,rt,rd,sa;
switch((fn=nmtab[insn].code)&0x3f){
case 000: /* shift */
case 002:
case 003:
case 004:
case 006:
case 007:
case 024:
case 026:
case 027:
case 070:
case 072:
case 073:
case 074:
case 076:
case 077:
scan_sym(tmpBuf);
rd=regnum(tmpBuf);
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
scan_sym(tmpBuf);
if(((fn&7)<4)||((fn&0x3f)>0x3b)){ /* immediate */
sa=gen_val(tmpBuf);
if(sa>31){
sa &= 0x1f;
fn &= 4;
}
else if(sa<0){
sa &= 0x1f;
}
rs=0;
}
else{ /* variable */
sa=0;
rs=regnum(tmpBuf);
}
break;
case 010: /* jr,jalr,sys,bp */
case 011:
case 014:
case 015:
if((fn&7)<4){ /* immediate */
scan_sym(tmpBuf);
rs=regnum(tmpBuf);
rt=rd=sa=0;
if(fn&1){ /* jalr */
int temp;
scan_sym(tmpBuf);
rd=regnum(tmpBuf);
temp=rd;
rd=rs;
rs=temp;
}
}
else if((fn&7)==4){ /* Sys */
rs=rt=rd=sa=0;
}
else {
rs=rt=rd=sa=0;
scan_sym(tmpBuf);
if(tmpBuf[0]!=0){
sa=gen_val(tmpBuf);
rd=sa>>5;
rt=sa>>10;
rs=sa>>15;
}
}
break;
case 020: /* hi/lo */
case 021:
case 022:
case 023:
scan_sym(tmpBuf);
rd=regnum(tmpBuf);
if(fn&1){ /* to */
rs=rd;
rd=rt=sa=0;
}
else{ /* from */
rs=rt=sa=0;
}
break;
case 030: /* mul/div */
case 031:
case 032:
case 033:
case 034:
case 035:
case 036:
case 037:
rd=sa=0;
scan_sym(tmpBuf);
rs=regnum(tmpBuf);
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
break;
case 040: /* 3-Op */
case 041:
case 042:
case 043:
case 044:
case 045:
case 046:
case 047:
case 052: /* slt,sltu */
case 053:
case 054:
case 055:
case 056:
case 057:
case 012:/* MOVZ */
case 013:/* MOVN */
sa=0;
scan_sym(tmpBuf);
rd=regnum(tmpBuf);
scan_sym(tmpBuf);
rs=regnum(tmpBuf);
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
break;
case 001:/* MOVF/MOVT */
sa=0;
scan_sym(tmpBuf);
rd=regnum(tmpBuf);
scan_sym(tmpBuf);
rs=regnum(tmpBuf);
scan_sym(tmpBuf);
rt=(gen_val(tmpBuf)&0x7)<<2;
if(strcmp(tmpBuf,"cc0")==0) rt=(0<<2);
if(strcmp(tmpBuf,"cc1")==0) rt=(1<<2);
if(strcmp(tmpBuf,"cc2")==0) rt=(2<<2);
if(strcmp(tmpBuf,"cc3")==0) rt=(3<<2);
if(strcmp(tmpBuf,"cc4")==0) rt=(4<<2);
if(strcmp(tmpBuf,"cc5")==0) rt=(5<<2);
if(strcmp(tmpBuf,"cc6")==0) rt=(6<<2);
if(strcmp(tmpBuf,"cc7")==0) rt=(7<<2);
break;
case 060:/* trap */
case 061:
case 062:
case 063:
case 064:
case 066:
rd=sa=0;
scan_sym(tmpBuf);
rs=regnum(tmpBuf);
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
scan_sym(tmpBuf);
if(tmpBuf[0]!='\0'){
rd = sa = gen_val(tmpBuf) & 0x3ff;
sa &= 0x1f;
rd >>= 5;
}
break;
case 067:/* COPz */
default:
rs=sa=0;
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
scan_sym(tmpBuf);
rd=regnum(tmpBuf);
fn &= 0xffffffc0;
}
fn |= ((rs&0x1f)<<21)|((rt&0x1f)<<16)|((rd&0x1f)<<11)|((sa&0x1f)<<6);
put_word(PC,fn);
}
static void I_TYPE(int insn)
{
int rs,rt;
long imm;
int cl;
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
switch(nmtab[insn].code){
case _CODE(001,0)|(000<<16): /* BLTZ */
case _CODE(001,0)|(001<<16): /* BGEZ */
case _CODE(001,0)|(002<<16): /* BLTZL */
case _CODE(001,0)|(003<<16): /* BFEZL */
case _CODE(001,0)|(020<<16): /* BLTZAL */
case _CODE(001,0)|(021<<16): /* BGEZAL */
case _CODE(001,0)|(022<<16): /* BLTZALL */
case _CODE(001,0)|(023<<16): /* BFEZALL */
case _CODE(006,0): /* BLEZ */
case _CODE(007,0): /* BGTZ */
case _CODE(026,0): /* BLEZL */
case _CODE(027,0): /* BGTZL */
rs=rt;
rt=(nmtab[insn].code&0x001f0000)>>16;
scan_sym(tmpBuf);
if((cl=check_label(tmpBuf))==ADDR){
imm = label_value;
imm = ((imm&0xffff)-(PC&0xffff)-4)>>2;
}
else if(cl==LOCALB){
imm = (long)local_label[label_value&0xff];
imm = ((imm&0xffff)-(PC&0xffff)-4)>>2;
}
else if(cl==LOCALF){
cl = (for_index[label_value&0xff]+1) % MAXLOCALF;
for_llabel[label_value&0xff][cl]=PC;
typ_llabel[label_value&0xff][cl]=BC;
for_index[label_value&0xff]=cl;
imm = 0;
}
else {
int i;
i = search_label(tmpBuf);
if(i<0){
regist_unsolv(tmpBuf,PC,BC);
imm = 0;
}
else {
imm = (long)label_table[i].addr;
imm = ((imm&0xffff)-(PC&0xffff)-4)>>2;
}
}
break;
case _CODE(004,0): /* BEQ */
case _CODE(005,0): /* BNE */
case _CODE(024,0): /* BEQL */
case _CODE(025,0): /* BNEL */
rs=rt;
scan_sym(tmpBuf);
rt=regnum(tmpBuf);
scan_sym(tmpBuf);
if((cl=check_label(tmpBuf))==ADDR){
imm = label_value;
imm = ((imm&0xffff)-(PC&0xffff)-4)>>2;
}
else if(cl==LOCALB){
imm = (long)local_label[label_value&0xff];
imm = ((imm&0xffff)-(PC&0xffff)-4)>>2;
}
else if(cl==LOCALF){
cl = (for_index[label_value&0xff]+1) % MAXLOCALF;
for_llabel[label_value&0xff][cl]=PC;
typ_llabel[label_value&0xff][cl]=BC;
for_index[label_value&0xff]=cl;
imm = 0;
}
else {
int i;
i = search_label(tmpBuf);
if(i<0){
regist_unsolv(tmpBuf,PC,BC);
imm = 0;
}
else {
imm = (long)label_table[i].addr;
imm = ((imm&0xffff)-(PC&0xffff)-4)>>2;
}
}
break;
case _CODE(020,0)|(010<<21)|(000<<16):/* BC0F */
case _CODE(021,0)|(010<<21)|(000<<16):/* BC1F */
case _CODE(022,0)|(010<<21)|(000<<16):/* BC2F */
case _CODE(023,0)|(010<<21)|(000<<16):/* BC3F */
case _CODE(020,0)|(010<<21)|(001<<16):/* BC0T */
case _CODE(021,0)|(010<<21)|(001<<16):/* BC1T */
case _CODE(022,0)|(010<<21)|(001<<16):/* BC2T */
case _CODE(023,0)|(010<<21)|(001<<16):/* BC3T */
case _CODE(020,0)|(010<<21)|(002<<16):/* BC0FL */
case _CODE(021,0)|(010<<21)|(002<<16):/* BC1FL */
case _CODE(022,0)|(010<<21)|(002<<16):/* BC2FL */
case _CODE(023,0)|(010<<21)|(002<<16):/* BC3FL */
case _CODE(020,0)|(010<<21)|(003<<16):/* BC0TL */
case _CODE(021,0)|(010<<21)|(003<<16):/* BC1TL */
case _CODE(022,0)|(010<<21)|(003<<16):/* BC2TL */
case _CODE(023,0)|(010<<21)|(003<<16):/* BC3TL */
rs=0;
rt= -1;
if(strcmp(tmpBuf,"cc0")==0) rt=(0<<2);
if(strcmp(tmpBuf,"cc1")==0) rt=(1<<2);
if(strcmp(tmpBuf,"cc2")==0) rt=(2<<2);
if(strcmp(tmpBuf,"cc3")==0) rt=(3<<2);
if(strcmp(tmpBuf,"cc4")==0) rt=(4<<2);
if(strcmp(tmpBuf,"cc5")==0) rt=(5<<2);
if(strcmp(tmpBuf,"cc6")==0) rt=(6<<2);
if(strcmp(tmpBuf,"cc7")==0) rt=(7<<2);
if(rt<0)
rt=0;
else
scan_sym(tmpBuf);
if((cl=check_label(tmpBuf))==ADDR){
imm = label_value;
imm = ((imm&0xffff)-(PC&0xffff)-4)>>2;
}
else if(cl==LOCALB){
imm = (long)local_label[label_value&0xff];
imm = ((imm&0xffff)-(PC&0xffff)-4)>>2;
}
else if(cl==LOCALF){
cl = (for_index[label_value&0xff]+1) % MAXLOCALF;
for_llabel[label_value&0xff][cl]=PC;
typ_llabel[label_value&0xff][cl]=BC;
for_index[label_value&0xff]=cl;
imm = 0;
}
else {
int i;
i = search_label(tmpBuf);
if(i<0){
regist_unsolv(tmpBuf,PC,BC);
imm = 0;
}
else {
imm = (long)label_table[i].addr;
imm = ((imm&0xffff)-(PC&0xffff)-4)>>2;
}
}
break;
case _CODE(001,0)|(010<<16): /* TGEI */
case _CODE(001,0)|(011<<16): /* TGEI */
case _CODE(001,0)|(012<<16): /* TGEI */
case _CODE(001,0)|(013<<16): /* TGEI */
case _CODE(001,0)|(014<<16): /* TGEI */
case _CODE(001,0)|(016<<16): /* TGEI */
rs=rt;
rt=0;
scan_sym(tmpBuf);
imm = gen_val(tmpBuf);
break;
default:
scan_sym(tmpBuf);
rs=regnum(tmpBuf);
scan_sym(tmpBuf);
imm = gen_val(tmpBuf);
}
put_word(PC,nmtab[insn].code|((rs&0x1f)<<21)|((rt&0x1f)<<16)|(imm&0xffff));
}
static void J_TYPE(int insn)
{
ulong targ;
int cl;
scan_sym(tmpBuf);
if((cl=check_label(tmpBuf))==ADDR){
targ = gen_val(tmpBuf);
targ =(targ>>2)&0x3ffffff;
}
else if(cl==LOCALB){
targ = local_label[label_value&0xff];
targ =(targ>>2)&0x3ffffff;
}
else if(cl==LOCALF){
cl = (for_index[label_value&0xff]+1) % MAXLOCALF;
for_llabel[label_value&0xff][cl]=PC;
typ_llabel[label_value&0xff][cl]=JMP;
for_index[label_value&0xff]=cl;
targ = 0;
}
else {
int i;
i = search_label(tmpBuf);
if(i<0){
regist_unsolv(tmpBuf,PC,JMP);
targ = 0;
}
else {
targ = label_table[i].addr;
targ=(targ>>2)&0x3ffffff;
}
}
put_word(PC,nmtab[insn].code|targ);
}
static void L_TYPE(int insn)
{
long offset;
int rt,base;
scan_sym(tmpBuf); /* rt */
rt=regnum(tmpBuf);
scan_sym(tmpBuf); /* offset */
offset= gen_val(tmpBuf);
if(nmtab[insn].code==_CODE(017,0)){ /* lui */
base=0;
}
else{
scan_sym(tmpBuf); /* base */
base=regnum(tmpBuf);
}
put_word(PC,nmtab[insn].code|((base&0x1f)<<21)|((rt&0x1f)<<16)|(offset&0xffff));
}
static void C_TYPE(int insn)
{
put_word(PC,nmtab[insn].code);
}
static void Z_TYPE(int insn)
{
long offset;
int rt,base;
scan_sym(tmpBuf); /* operation */
rt=gen_val(tmpBuf)&0x1f;
if(strcmp(tmpBuf,"Index_Inv_I" )==0) rt=0x0;
if(strcmp(tmpBuf,"Index_Writeback_Inv_D" )==0) rt=0x1;
if(strcmp(tmpBuf,"Index_Writeback_Inv_SD" )==0) rt=0x3;
if(strcmp(tmpBuf,"Index_Load_Tag_I" )==0) rt=0x4;
if(strcmp(tmpBuf,"Index_Load_Tag_D" )==0) rt=0x5;
if(strcmp(tmpBuf,"Index_Load_Tag_SI" )==0) rt=0x6;
if(strcmp(tmpBuf,"Index_Load_Tag_SD" )==0) rt=0x7;
if(strcmp(tmpBuf,"Index_Store_Tag_I" )==0) rt=0x8;
if(strcmp(tmpBuf,"Index_Store_Tag_D" )==0) rt=0x9;
if(strcmp(tmpBuf,"Index_Store_Tag_SI" )==0) rt=0xa;
if(strcmp(tmpBuf,"Index_Store_Tag_SD" )==0) rt=0xb;
if(strcmp(tmpBuf,"Create_Dirty_D" )==0) rt=0xd;
if(strcmp(tmpBuf,"Create_Dirty_SD" )==0) rt=0xf;
if(strcmp(tmpBuf,"Hit_Inv_I" )==0) rt=0x10;
if(strcmp(tmpBuf,"Hit_Inv_D" )==0) rt=0x11;
if(strcmp(tmpBuf,"Hit_Inv_SI" )==0) rt=0x12;
if(strcmp(tmpBuf,"Hit_Inv_SD" )==0) rt=0x13;
if(strcmp(tmpBuf,"Hit_Writeback_Inv_D" )==0) rt=0x15;
if(strcmp(tmpBuf,"Fill_I" )==0) rt=0x14;
if(strcmp(tmpBuf,"Hit_Writeback_D" )==0) rt=0x19;
if(strcmp(tmpBuf,"Hit_Writeback_SD" )==0) rt=0x1b;
if(strcmp(tmpBuf,"Hit_Writeback_I" )==0) rt=0x18;
if(strcmp(tmpBuf,"load" )==0) rt=0x00;
if(strcmp(tmpBuf,"store" )==0) rt=0x01;
if(strcmp(tmpBuf,"load_streamed" )==0) rt=0x04;
if(strcmp(tmpBuf,"store_streamed" )==0) rt=0x05;
if(strcmp(tmpBuf,"load_retained" )==0) rt=0x06;
if(strcmp(tmpBuf,"store_retained" )==0) rt=0x07;
if(strcmp(tmpBuf,"writeback_invalidate" )==0) rt=0x19;
scan_sym(tmpBuf); /* offset */
offset= gen_val(tmpBuf);
scan_sym(tmpBuf); /* base */
base=regnum(tmpBuf);
put_word(PC,nmtab[insn].code|((base&0x1f)<<21)|((rt&0x1f)<<16)|(offset&0xffff));
}
static void X_TYPE(int insn) /* COP1X */
{
int fd,fr,fs,ft;
scan_sym(tmpBuf);
switch(nmtab[insn].code&0x3f){
case 000:
case 001:
case 010:
case 011:
fs=regnum(tmpBuf);
scan_sym(tmpBuf);
ft=regnum(tmpBuf);
scan_sym(tmpBuf);
fr=regnum(tmpBuf);
fd=0;
break;
case 040:
case 041:
case 050:
case 051:
case 060:
case 061:
case 070:
case 071:
fd=regnum(tmpBuf);
scan_sym(tmpBuf);
fr=regnum(tmpBuf);
scan_sym(tmpBuf);
fs=regnum(tmpBuf);
scan_sym(tmpBuf);
ft=regnum(tmpBuf);
break;
default:/* prefx */
fd=0;
fs=gen_val(tmpBuf)&0x1f;
if(strcmp(tmpBuf,"load" )==0) fs=0x00;
if(strcmp(tmpBuf,"store" )==0) fs=0x01;
if(strcmp(tmpBuf,"load_streamed" )==0) fs=0x04;
if(strcmp(tmpBuf,"store_streamed" )==0) fs=0x05;
if(strcmp(tmpBuf,"load_retained" )==0) fs=0x06;
if(strcmp(tmpBuf,"store_retained" )==0) fs=0x07;
if(strcmp(tmpBuf,"writeback_invalidate")==0) fs=0x19;
scan_sym(tmpBuf);
ft=regnum(tmpBuf);
scan_sym(tmpBuf);
fr=regnum(tmpBuf);
}
put_word(PC,nmtab[insn].code|((fr&0x1f)<<21)|((ft&0x1f)<<16)|((fs&0x1f)<<11)|((fd&0x1f)<<6));
}
static long asmcp1(ulong, char*);
static ulong asmcpu(ulong pc, char *buf)
{
int i;
long tmp;
int reg;
for(i=0;i<MAXTAB;i++)
if(strcmp(tmpBuf,nmtab[i].nm)==0) break;
if(i>=MAXTAB){
if(strcmp(tmpBuf,"nop")==0){
put_word(PC,0);
return PC+4;
}
if(strcmp(tmpBuf,".org")==0){
scan_sym(tmpBuf);
return (ulong)gen_val(tmpBuf);
}
if(strcmp(tmpBuf,".align")==0){
scan_sym(tmpBuf);
tmp = gen_val(tmpBuf);
return PC+(tmp-(PC%tmp));
}
if(strcmp(tmpBuf,".word")==0){
scan_sym(tmpBuf);
while(tmpBuf[0]!='\0'){
tmp = gen_val(tmpBuf);
put_word(PC,tmp);
PC += 4;
scan_sym(tmpBuf);
}
return PC;
}
if(strcmp(tmpBuf,"move")==0){
int reg2;
scan_sym(tmpBuf);
reg = regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
reg2 = regnum(tmpBuf)&0x1f;
put_word(PC,_CODE(000,045)|(reg2<<16)|(reg<<11));
return PC+4;
}
if(strcmp(tmpBuf,"li")==0){
scan_sym(tmpBuf);
reg = regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
tmp = gen_val(tmpBuf);
if((tmp&0xffff0000)==0){
put_word(PC,_CODE(015,0)|(reg<<16)|(tmp&0xffff));
return PC+4;
}
if((tmp&0xffff)==0){
put_word(PC,_CODE(017,0)|(reg<<16)|((tmp>>16)&0xffff));
return PC+4;
}
if(tmp&0x8000){
if((((tmp>>16)+1)&0xffff)==0){/* sign extended */
put_word(PC,_CODE(011,0)|(reg<<16)|(tmp&0xffff));
return PC+4;
}
}
put_word(PC+0,_CODE(017,0)|(reg<<16)|((tmp>>16)&0xffff));
put_word(PC+4,_CODE(015,0)|(reg<<21)|(reg<<16)|(tmp&0xffff));
return PC+8;
}
if(strcmp(tmpBuf,"la")==0){
int cl;
scan_sym(tmpBuf);
reg = regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
if((cl=check_label(tmpBuf))==ADDR){
tmp = gen_val(tmpBuf);
}
else if(cl==LOCALB){
tmp = local_label[label_value&0xff];
}
else if(cl==LOCALF){
cl = (for_index[label_value&0xff]+1) % MAXLOCALF;
for_llabel[label_value&0xff][cl]=PC;
typ_llabel[label_value&0xff][cl]=LA;
for_index[label_value&0xff]=cl;
tmp = 0;
}
else {
int i;
i = search_label(tmpBuf);
if(i<0){
regist_unsolv(tmpBuf,PC,LA);
tmp = 0;
}
else {
tmp = label_table[i].addr;
}
}
put_word(PC+0,_CODE(017,0)|(reg<<16)|((tmp>>16)&0xffff));
put_word(PC+4,_CODE(015,0)|(reg<<21)|(reg<<16)|(tmp&0xffff));
return PC+8;
}
if(tmpBuf[0]==0)
return pc;
if(asmcp1(pc,tmpBuf)<0){
fprintf(stderr,"%d: unknown nmemonic!\n",linenum);
return pc;
}
else
return pc+4;
}
(nmtab[i].type)(i);
return pc+4;
}
static long asmcp1(ulong pc, char *buf)
{
int i;
int fmt;
int fd,fs,ft;
i=strlen(buf);
switch(buf[i-1]){
case 's':
fmt=000; break;
case 'd':
fmt=001; break;
case 'w':
fmt=004; break;
case 'l':
fmt=005; break;
default:
fprintf(stderr,"%d: illegal format:%c\n",linenum,buf[i-1]);
return -1;
}
if(buf[i-2]!='.'){
fprintf(stderr,"%d: unknown nmemonic(cp1):%s\n",linenum,buf);
return -1;
}
buf[i-2]=0;
for(i=0;i<=077;i++)
if(strcmp(fnam[i],buf)==0) break;
if(i>077){
if(strcmp(buf,"movf")==0) {i=021; ft=0;}
else if(strcmp(buf,"movt")==0) {i=021; ft=1;}
else if(strcmp(buf,"movz")==0) i=022;
else if(strcmp(buf,"movn")==0) i=023;
else if(strcmp(buf,"recip")==0) i=025;
else if(strcmp(buf,"rsqrt")==0) i=026;
else{
fprintf(stderr,"%d: unknown nmemonic(cp1):%s\n",linenum,buf);
return -1;
}
switch(i){
case 022:
case 023:
scan_sym(tmpBuf);
fd=regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
fs=regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
ft=regnum(tmpBuf)&0x1f;
break;
case 026:
case 027:
scan_sym(tmpBuf);
fd=regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
fs=regnum(tmpBuf)&0x1f;
ft=0;
break;
default:
scan_sym(tmpBuf);
fd=regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
fs=regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
ft|=(gen_val(tmpBuf)&0x7)<<2;
if(strcmp(tmpBuf,"cc0")==0) ft|=(0<<2);
if(strcmp(tmpBuf,"cc1")==0) ft|=(1<<2);
if(strcmp(tmpBuf,"cc2")==0) ft|=(2<<2);
if(strcmp(tmpBuf,"cc3")==0) ft|=(3<<2);
if(strcmp(tmpBuf,"cc4")==0) ft|=(4<<2);
if(strcmp(tmpBuf,"cc5")==0) ft|=(5<<2);
if(strcmp(tmpBuf,"cc6")==0) ft|=(6<<2);
if(strcmp(tmpBuf,"cc7")==0) ft|=(7<<2);
}
}
else{ /* MIPS-I/II/III */
scan_sym(tmpBuf);
if(i>=060){ /* compare */
fd= -1;
if(strcmp(tmpBuf,"cc0")==0) fd=(0<<2);
if(strcmp(tmpBuf,"cc1")==0) fd=(1<<2);
if(strcmp(tmpBuf,"cc2")==0) fd=(2<<2);
if(strcmp(tmpBuf,"cc3")==0) fd=(3<<2);
if(strcmp(tmpBuf,"cc4")==0) fd=(4<<2);
if(strcmp(tmpBuf,"cc5")==0) fd=(5<<2);
if(strcmp(tmpBuf,"cc6")==0) fd=(6<<2);
if(strcmp(tmpBuf,"cc7")==0) fd=(7<<2);
if(fd<0) /* no cc */
fd=0;
else
scan_sym(tmpBuf);
fs=regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
ft=regnum(tmpBuf);
}
else{
fd=regnum(tmpBuf)&0x1f;
scan_sym(tmpBuf);
fs=regnum(tmpBuf)&0x1f;
if(i<4){
scan_sym(tmpBuf);
ft=regnum(tmpBuf)&0x1f;
}
else
ft=0;
}
}
put_word(pc,(021<<26)|(1<<25)|(fmt<<21)|(ft<<16)|(fs<<11)|(fd<<6)|i);
return 0;
}
#define LittleEndian 0
#define BigEndian 1
static int endian = LittleEndian;
void asmips(char *base, FILE *fp)
{
int i;
linenum = 0;
labelp = -1;
unsolvedp = -1;
for(i=1;i<256;i++)
for_index[i] = -1;
if(*base!='\0')
PC = (ulong)gen_val(base);
printf("%08x ",PC);fflush(stdout);
while(fgets(Line,MAXBUFF,fp)!=NULL){
linep = Line;
linenum++;
scan_sym(tmpBuf);
if(tmpBuf[0]=='q')/* quit */
break;
if(tmpBuf[0]=='\0')/* null line */
goto next;
if(tmpBuf[0]=='#') /* comment line */
goto next;
i = strlen(tmpBuf);
if(tmpBuf[i-1]==':'){ /* label */
/* process label */
tmpBuf[i-1]='\0';
if(i=islocal(tmpBuf)){
local_label[i&0xff]=PC;
solve_local(i&0xff);
}
else if(regist_label(tmpBuf,PC)<0)
fprintf(stderr,"%d: label error!\n",linenum);
scan_sym(tmpBuf);
if(tmpBuf[0]=='\0')
goto next;
}
PC = asmcpu(PC,tmpBuf);
next:
printf("%08x ",PC);fflush(stdout);
}
solve_label();
}